home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** A collection of useful high-level File Manager routines.
- **
- ** by Jim Luther, Apple Developer Technical Support
- **
- ** File: MoreFilesExtras.c
- **
- ** Copyright © 1992-1994 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DSC Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
- */
-
- #ifndef __MOREFILESEXTRAS__
- #include "MoreFilesExtras.h"
- #endif
-
- /*****************************************************************************/
-
- /* local data structures */
-
- /* The DeleteEnumGlobals structure is used to minimize the amount of
- ** stack space used when recursively calling DeleteLevel and to hold
- ** global information that might be needed at any time. */
- struct DeleteEnumGlobals
- {
- OSErr error; /* temporary holder of results - saves 2 bytes of stack each level */
- Str63 itemName; /* the name of the current item */
- UniversalFMPB myPB; /* the parameter block used for PBGetCatInfo calls */
- };
- typedef struct DeleteEnumGlobals DeleteEnumGlobals;
- typedef DeleteEnumGlobals *DeleteEnumGlobalsPtr;
-
- /*****************************************************************************/
-
- /* static prototypes */
-
- static void pcpy(StringPtr d,
- StringPtr s);
-
- static Ptr GetSearchBuffer(long *buffSize);
-
- static void DeleteLevel(long dirToDelete,
- DeleteEnumGlobalsPtr theGlobals);
-
- /*****************************************************************************/
-
- /* Copy a Pascal-string. */
- static void pcpy(StringPtr d,
- StringPtr s)
- {
- short i;
-
- i = *s;
- do {
- d[i] = s[i];
- } while (i--);
- }
-
- /*****************************************************************************/
-
- /* A utility routine called by NameFileSearch and CreatorTypeFileSearch to
- ** allocate a optimization buffer. */
-
- static Ptr GetSearchBuffer(long *buffSize)
- {
- Ptr tempPtr;
-
- *buffSize = 0x00004000; /* start by trying for a 16K buffer */
- while (*buffSize) { /* and keep trying until *buffSize is zero */
- tempPtr = NewPtr(*buffSize);
- if (tempPtr)
- break; /* got it */
- else
- *buffSize -= 0x00000400; /* didn't get it, subtract 1K and try again */
- }
- return (tempPtr);
- }
-
- /*****************************************************************************/
-
- pascal OSErr NameFileSearch(StringPtr volName,
- short vRefNum,
- const Str255 fileName,
- FSSpecPtr matches,
- long reqMatchCount,
- long *actMatchCount,
- Boolean newSearch,
- Boolean partial)
- {
- CInfoPBRec searchInfo1, searchInfo2;
- HParamBlockRec pb;
- OSErr error;
- static CatPositionRec catPosition;
- static short lastVRefNum = 0;
-
- /* get the real volume reference number */
- error = DetermineVRefNum(volName, vRefNum, &vRefNum);
- if (error != noErr)
- return (error);
-
- pb.csParam.ioNamePtr = nil;
- pb.csParam.ioVRefNum = vRefNum;
- pb.csParam.ioMatchPtr = matches;
- pb.csParam.ioReqMatchCount = reqMatchCount;
- pb.csParam.ioSearchBits = (partial) ? /* tell CatSearch what we're looking for: */
- (fsSBPartialName + fsSBFlAttrib) : /* partial name file matches or */
- (fsSBFullName + fsSBFlAttrib); /* full name file matches */
- pb.csParam.ioSearchInfo1 = &searchInfo1;
- pb.csParam.ioSearchInfo2 = &searchInfo2;
- pb.csParam.ioSearchTime = 0;
- if ((newSearch) || /* If caller specified new search */
- (lastVRefNum != vRefNum)) /* or if last search was to another volume, */
- catPosition.initialize = 0; /* then search from beginning of catalog */
- pb.csParam.ioCatPosition = catPosition;
- pb.csParam.ioOptBuffer = GetSearchBuffer(&pb.csParam.ioOptBufSize);
-
- /* search for fileName */
- searchInfo1.hFileInfo.ioNamePtr = (StringPtr)fileName;
- searchInfo2.hFileInfo.ioNamePtr = nil;
-
- /* only match files (not directories) */
- searchInfo1.hFileInfo.ioFlAttrib = 0x00;
- searchInfo2.hFileInfo.ioFlAttrib = 0x10;
-
- error = PBCatSearchSync((CSParamPtr)&pb);
-
- if ((error == noErr) || /* If no errors or the end of catalog was */
- (error == eofErr)) /* found, then the call was successful so */
- *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */
- else
- *actMatchCount = 0; /* else no matches found */
-
- if ((error == noErr) || /* If no errors */
- (error == catChangedErr)) /* or there was a change in the catalog */
- {
- catPosition = pb.csParam.ioCatPosition;
- lastVRefNum = vRefNum;
- /* we can probably start the next search where we stopped this time */
- }
- else
- catPosition.initialize = 0;
- /* start the next search from beginning of catalog */
-
- if (pb.csParam.ioOptBuffer)
- DisposPtr(pb.csParam.ioOptBuffer);
-
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr CreatorTypeFileSearch(StringPtr volName,
- short vRefNum,
- OSType creator,
- OSType fileType,
- FSSpecPtr matches,
- long reqMatchCount,
- long *actMatchCount,
- Boolean newSearch)
- {
- CInfoPBRec searchInfo1, searchInfo2;
- HParamBlockRec pb;
- OSErr error;
- static CatPositionRec catPosition;
- static short lastVRefNum = 0;
-
- /* get the real volume reference number */
- error = DetermineVRefNum(volName, vRefNum, &vRefNum);
- if (error != noErr)
- return (error);
-
- pb.csParam.ioNamePtr = nil;
- pb.csParam.ioVRefNum = vRefNum;
- pb.csParam.ioMatchPtr = matches;
- pb.csParam.ioReqMatchCount = reqMatchCount;
- pb.csParam.ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo; /* Looking for finder info file matches */
- pb.csParam.ioSearchInfo1 = &searchInfo1;
- pb.csParam.ioSearchInfo2 = &searchInfo2;
- pb.csParam.ioSearchTime = 0;
- if ((newSearch) || /* If caller specified new search */
- (lastVRefNum != vRefNum)) /* or if last search was to another volume, */
- catPosition.initialize = 0; /* then search from beginning of catalog */
- pb.csParam.ioCatPosition = catPosition;
- pb.csParam.ioOptBuffer = GetSearchBuffer(&pb.csParam.ioOptBufSize);
-
- /* no fileName */
- searchInfo1.hFileInfo.ioNamePtr = nil;
- searchInfo2.hFileInfo.ioNamePtr = nil;
-
- /* only match files (not directories) */
- searchInfo1.hFileInfo.ioFlAttrib = 0x00;
- searchInfo2.hFileInfo.ioFlAttrib = 0x10;
-
- /* search for creator; if creator = 0x00000000, ignore creator */
- searchInfo1.hFileInfo.ioFlFndrInfo.fdCreator = creator;
- searchInfo2.hFileInfo.ioFlFndrInfo.fdCreator = (creator == (OSType)0x00000000) ?
- (OSType)0x00000000 :
- (OSType)0xffffffff;
-
- /* search for fileType; if fileType = 0x00000000, ignore fileType */
- searchInfo1.hFileInfo.ioFlFndrInfo.fdType = fileType;
- searchInfo2.hFileInfo.ioFlFndrInfo.fdType = (fileType == (OSType)0x00000000) ?
- (OSType)0x00000000 :
- (OSType)0xffffffff;
-
- /* zero all other FInfo fields */
- searchInfo1.hFileInfo.ioFlFndrInfo.fdFlags = 0;
- searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.v = 0;
- searchInfo1.hFileInfo.ioFlFndrInfo.fdLocation.h = 0;
- searchInfo1.hFileInfo.ioFlFndrInfo.fdFldr = 0;
-
- searchInfo2.hFileInfo.ioFlFndrInfo.fdFlags = 0;
- searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0;
- searchInfo2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0;
- searchInfo2.hFileInfo.ioFlFndrInfo.fdFldr = 0;
-
- error = PBCatSearchSync((CSParamPtr)&pb);
-
- if ((error == noErr) || /* If no errors or the end of catalog was */
- (error == eofErr)) /* found, then the call was successful so */
- *actMatchCount = pb.csParam.ioActMatchCount; /* return the match count */
- else
- *actMatchCount = 0; /* else no matches found */
-
- if ((error == noErr) || /* If no errors */
- (error == catChangedErr)) /* or there was a change in the catalog */
- {
- catPosition = pb.csParam.ioCatPosition;
- lastVRefNum = vRefNum;
- /* we can probably start the next search where we stopped this time */
- }
- else
- catPosition.initialize = 0;
- /* start the next search from beginning of catalog */
-
- if (pb.csParam.ioOptBuffer)
- DisposPtr(pb.csParam.ioOptBuffer);
-
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DetermineVRefNum(StringPtr pathname,
- short vRefNum,
- short *realVRefNum)
- {
- HParamBlockRec pb;
- Str255 tempPathname;
- OSErr error;
-
- pb.volumeParam.ioVRefNum = vRefNum;
- if (pathname == nil) {
- pb.volumeParam.ioNamePtr = nil;
- pb.volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
- }
- else {
- pcpy((StringPtr)tempPathname, pathname); /* make a copy of the string and */
- pb.volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */
- pb.volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */
- }
- error = PBHGetVInfoSync(&pb);
- *realVRefNum = pb.volumeParam.ioVRefNum;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr UnmountAndEject(StringPtr pathname,
- short vRefNum)
- {
- HParamBlockRec pb;
- Str255 tempPathname;
- short driveNum;
- Boolean ejected, ejectable;
- DrvQElPtr drvQElem;
- OSErr error;
-
- pb.volumeParam.ioVRefNum = vRefNum;
- if (pathname == nil) {
- pb.volumeParam.ioNamePtr = nil;
- pb.volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
- }
- else {
- pcpy((StringPtr)tempPathname, pathname); /* make a copy of the string and */
- pb.volumeParam.ioNamePtr = (StringPtr)tempPathname; /* use the copy so original isn't trashed */
- pb.volumeParam.ioVolIndex = -1; /* use ioNamePtr/ioVRefNum combination */
- }
- error = PBHGetVInfoSync(&pb);
- if (error == noErr)
- {
- if (pb.volumeParam.ioVDrvInfo != 0)
- {
- /* the volume is online and not ejected */
- ejected = false;
-
- /* Get the drive number */
- driveNum = pb.volumeParam.ioVDrvInfo;
- }
- else
- {
- /* the volume is ejected or offline */
-
- /* Is it ejected? */
- ejected = (pb.volumeParam.ioVDRefNum > 0);
-
- if (ejected)
- {
- /* If ejected, the drive number is ioVDRefNum */
- driveNum = pb.volumeParam.ioVDRefNum;
- }
- else
- {
- /* If offline, the drive number is the negative of ioVDRefNum */
- driveNum = (short)-pb.volumeParam.ioVDRefNum;
- }
- }
-
- /* find the drive queue element */
- drvQElem = (DrvQElPtr)(GetDrvQHdr()->qHead);
- while ((drvQElem != nil) && (drvQElem->dQDrive != driveNum))
- drvQElem = (DrvQElPtr)drvQElem->qLink;
-
- if (drvQElem != nil)
- {
- /* is the volume ejectable */
- ejectable = (*((Ptr)((Ptr)drvQElem - 3)) != 8);
- }
- else
- {
- /* didn't find the drive!! */
- ejectable = false;
- }
-
- /* unmount the volume */
- pb.volumeParam.ioNamePtr = nil;
- /* ioVRefNum is already filled in from PBHGetVInfo */
- error = PBUnmountVol((ParmBlkPtr)&pb);
- if (error == noErr)
- {
- if (ejectable && !ejected)
- {
- /* eject the media from the drive if needed */
- pb.volumeParam.ioVRefNum = driveNum;
- error = PBEject((ParmBlkPtr)&pb);
- }
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr OnLine(FSSpecPtr volumes,
- short reqVolCount,
- short *actVolCount,
- short *volIndex)
- {
- HParamBlockRec pb;
- OSErr error = noErr;
- FSSpec *endVolArray = volumes + reqVolCount;
-
- *actVolCount = 0;
- for (; (volumes < endVolArray) && (error == noErr); ++volumes)
- {
- pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name;
- pb.volumeParam.ioVolIndex = *volIndex;
- error = PBHGetVInfoSync(&pb);
- if (error == noErr)
- {
- volumes->parID = fsRtParID; /* the root directory's parent is 1 */
- volumes->vRefNum = pb.volumeParam.ioVRefNum;
- ++*volIndex;
- ++*actVolCount;
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetDirID(short vRefNum,
- long dirID,
- StringPtr name,
- long *theDirID,
- Boolean *isDirectory)
- {
- CInfoPBRec pb;
- OSErr error;
-
- pb.hFileInfo.ioNamePtr = name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- error = PBGetCatInfoSync(&pb);
- *theDirID = pb.hFileInfo.ioDirID;
- *isDirectory = (pb.hFileInfo.ioFlAttrib & 0x10) != 0;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DirIDFromFSSpec(const FSSpec *spec,
- long *theDirID,
- Boolean *isDirectory)
- {
- return (GetDirID(spec->vRefNum, spec->parID, (StringPtr)spec->name,
- theDirID, isDirectory));
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetDirName(short vRefNum,
- long dirID,
- StringPtr name)
- {
- CInfoPBRec pb;
-
- pb.hFileInfo.ioNamePtr = name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = -1; /* get information about ioDirID */
- return (PBGetCatInfoSync(&pb));
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetParentID(short vRefNum,
- long dirID,
- StringPtr name,
- long *parID)
- {
- CInfoPBRec pb;
- OSErr error;
-
- pb.hFileInfo.ioNamePtr = name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- error = PBGetCatInfoSync(&pb);
- *parID = pb.hFileInfo.ioFlParID;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetFilenameFromPathname(const Str255 pathname,
- Str255 filename)
- {
- short index;
- short nameEnd;
-
- /* default to no filename */
- filename[0] = 0;
-
- /* check for no pathname */
- if (pathname == nil)
- return(notAFileErr);
-
- /* get string length */
- index = pathname[0];
-
- /* check for empty string */
- if (index == 0)
- return(notAFileErr);
-
- /* skip over last trailing colon (if any) */
- if (pathname[index] == ':')
- --index;
-
- /* save the end of the string */
- nameEnd = index;
-
- /* if pathname ends with multiple colons, then this pathname refers */
- /* to a directory, not a file */
- if (pathname[index] == ':')
- return (notAFileErr);
-
-
- /* parse backwards until we find a colon or hit the beginning of the pathname */
- while ((pathname[index] != ':') && (index != 0))
- --index;
-
- /* if we parsed to the beginning of the pathname and the pathname ended */
- /* with a colon, then pathname is a full pathname to a volume, not a file */
- if ((index == 0) && (pathname[pathname[0]]))
- return (notAFileErr);
-
- /* get the filename and return noErr */
- filename[0] = (char)(nameEnd - index);
- BlockMove(&pathname[index+1], &filename[1], nameEnd - index);
- return (noErr);
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetObjectLocation(short vRefNum,
- long dirID,
- StringPtr pathname,
- short *realVRefNum,
- long *realParID,
- Str255 realName,
- Boolean *isDirectory)
- {
- OSErr error;
- long theDirID;
- Str255 parPathname;
-
- error = DetermineVRefNum(pathname, vRefNum, realVRefNum);
- if (error == noErr)
- {
- error = GetParentID(vRefNum, dirID, pathname, realParID);
- if (error == noErr)
- {
- /* The object is present */
-
- /* Find out if the object is a file or directory and */
- /* if object is a directory, get its dirID */
- error = GetDirID(vRefNum, dirID, pathname, &theDirID, isDirectory);
- if (error == noErr)
- {
- if (*isDirectory)
- {
- /* it's a directory, get its name */
- error = GetDirName(*realVRefNum, theDirID, realName);
- }
- else
- {
- /* it's a file - parse to get the file name */
- error = GetFilenameFromPathname(pathname, realName);
- }
- }
- }
- else if (error == fnfErr)
- {
- /* The object isn't present - see if its parent is present */
-
- /* parse to get the object name from end of pathname */
- error = GetFilenameFromPathname(pathname, realName);
- /* if we can't get the object name from the end, we can't continue */
- if (error == noErr)
- {
- /* get a copy of the pathname */
- pcpy(parPathname, pathname);
-
- /* remove the object name */
- parPathname[0] -= realName[0];
- /* and the trailing colon (if any) */
- if (pathname[pathname[0]] == ':')
- --parPathname[0];
-
- /* OK, now get the parent's directory ID */
- error = GetDirID(vRefNum, dirID, parPathname, realParID, isDirectory);
-
- *isDirectory = false; /* we don't know what the object is really going to be */
- }
- if (error != noErr)
- error = dirNFErr; /* couldn't find parent directory */
- else
- error = fnfErr; /* we found the parent, but not the file */
- }
- }
-
- /* if we get anything other than noErr or fnfErr, clear the results */
- if ((error != noErr) && (error != fnfErr))
- {
- *realVRefNum = 0;
- *realParID = 0;
- realName[0] = 0;
- *isDirectory = false;
- }
-
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetDirItems(short vRefNum,
- long dirID,
- StringPtr name,
- Boolean getFiles,
- Boolean getDirectories,
- FSSpecPtr items,
- short reqItemCount,
- short *actItemCount,
- short *itemIndex) /* start with 1, then use what's returned */
- {
- CInfoPBRec pb;
- OSErr error = noErr;
- long theDirID;
- Boolean isDirectory;
- FSSpec *endItemsArray = items + reqItemCount;
-
- /* NOTE: If I could be sure that the caller passed a real vRefNum and real directory */
- /* to this routine, I could rip out calls to DetermineVRefNum and GetDirID and this */
- /* routine would be much faster because of the overhead of DetermineVRefNum and */
- /* GetDirID and because GetDirID blows away the directory index hint the Macintosh */
- /* file system keeps for indexed calls. I can't be sure, so for maximum throughput, */
- /* pass a big array of FSSpecs so you can get the directory's contents with few calls */
- /* to this routine. */
-
- /* get the real volume reference number */
- error = DetermineVRefNum(name, vRefNum, &pb.hFileInfo.ioVRefNum);
- if (error != noErr)
- return (error);
-
- /* and the real directory ID of this directory (and make sure it IS a directory */
- error = GetDirID(vRefNum, dirID, name, &theDirID, &isDirectory);
- if (error != noErr)
- return (error);
- else if (!isDirectory)
- return (dirNFErr);
-
-
- *actItemCount = 0;
- for (; (items < endItemsArray) && (error == noErr); )
- {
- pb.hFileInfo.ioNamePtr = (StringPtr) &items->name;
- pb.hFileInfo.ioDirID = theDirID;
- pb.hFileInfo.ioFDirIndex = *itemIndex;
- error = PBGetCatInfoSync(&pb);
- if (error == noErr)
- {
- items->parID = pb.hFileInfo.ioFlParID; /* return item's parID */
- items->vRefNum = pb.hFileInfo.ioVRefNum; /* return item's vRefNum */
- ++*itemIndex; /* prepare to get next item in directory */
-
- if (pb.hFileInfo.ioFlAttrib & 0x10) {
- if (getDirectories) {
- ++*actItemCount; /* keep this item */
- ++items; /* point to next item */
- }
- }
- else {
- if (getFiles) {
- ++*actItemCount; /* keep this item */
- ++items; /* point to next item */
- }
- }
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- static void DeleteLevel(long dirToDelete,
- DeleteEnumGlobalsPtr theGlobals)
- {
- long savedDir;
-
- do
- {
- /* prepare to delete directory */
- theGlobals->myPB.ciPB.dirInfo.ioNamePtr = (StringPtr)&theGlobals->itemName;
- theGlobals->myPB.ciPB.dirInfo.ioFDirIndex = 1; /* get first item */
- theGlobals->myPB.ciPB.dirInfo.ioDrDirID = dirToDelete; /* in this directory */
- theGlobals->error = PBGetCatInfoSync(&(theGlobals->myPB.ciPB));
- if (theGlobals->error == noErr)
- {
- savedDir = dirToDelete;
- /* We have an item. Is it a file or directory? */
- if ((theGlobals->myPB.ciPB.dirInfo.ioFlAttrib & 0x10) != 0)
- {
- /* it's a directory */
- savedDir = theGlobals->myPB.ciPB.dirInfo.ioDrDirID; /* save dirID of directory instead */
- DeleteLevel(theGlobals->myPB.ciPB.dirInfo.ioDrDirID, theGlobals); /* Delete its contents */
- theGlobals->myPB.ciPB.dirInfo.ioNamePtr = nil; /* prepare to delete directory */
- }
- if (theGlobals->error == noErr)
- {
- theGlobals->myPB.ciPB.dirInfo.ioDrDirID = savedDir; /* restore dirID */
- theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* delete this item */
- if (theGlobals->error == fLckdErr)
- {
- (void) PBHRstFLockSync(&(theGlobals->myPB.hPB)); /* unlock it */
- theGlobals->error = PBHDeleteSync(&(theGlobals->myPB.hPB)); /* and try again */
- }
- }
- }
- }
- while (theGlobals->error == noErr);
- if (theGlobals->error == fnfErr)
- theGlobals->error = noErr;
- }
-
- /*****************************************************************************/
-
- pascal OSErr DeleteDirectoryContents(short vRefNum,
- long dirID,
- StringPtr name)
- {
- DeleteEnumGlobals theGlobals;
- Boolean isDirectory;
- OSErr error;
-
- /* Get the real dirID and make sure it is a directory. */
- error = GetDirID(vRefNum, dirID, name, &dirID, &isDirectory);
- if (error != noErr)
- return (error);
- if (!isDirectory)
- return (dirNFErr);
-
- /* Get the real vRefNum */
- error = DetermineVRefNum(name, vRefNum, &vRefNum);
- if (error != noErr)
- return (error);
-
- /* Set up the globals we need to access from the recursive routine. */
- theGlobals.myPB.ciPB.dirInfo.ioVRefNum = vRefNum;
-
- /* Here we go into recursion land... */
- DeleteLevel(dirID, &theGlobals);
- return (theGlobals.error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr DeleteDirectory(short vRefNum,
- long dirID,
- StringPtr name)
- {
- OSErr error;
-
- /* Make sure a directory was specified and then delete its contents */
- error = DeleteDirectoryContents(vRefNum, dirID, name);
- if (error == noErr)
- {
- error = HDelete(vRefNum, dirID, name);
- if (error == fLckdErr)
- {
- (void) HRstFLock(vRefNum, dirID, name); /* unlock the directory locked by AppleShare */
- error = HDelete(vRefNum, dirID, name); /* and try again */
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr BumpDate(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, change its modification date to the current date/time. */
- {
- CInfoPBRec pb;
- OSErr error;
- unsigned long secs;
-
- pb.hFileInfo.ioNamePtr = name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- error = PBGetCatInfoSync(&pb);
- if (error == noErr)
- {
- GetDateTime(&secs);
- /* set mod date to current date, or one second into the future
- if mod date = current date */
- pb.hFileInfo.ioFlMdDat = (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
- pb.hFileInfo.ioDirID = dirID;
- error = PBSetCatInfoSync(&pb);
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpBumpDate(const FSSpec *spec)
- {
- return (BumpDate(spec->vRefNum, spec->parID, (StringPtr)spec->name));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ChangeCreatorType(short vRefNum,
- long dirID,
- const Str255 name,
- OSType creator,
- OSType fileType)
- {
- CInfoPBRec pb;
- OSErr error;
- long parID;
-
- pb.hFileInfo.ioNamePtr = (StringPtr)name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- error = PBGetCatInfoSync(&pb);
- if (error == noErr)
- {
- if (pb.hFileInfo.ioFlAttrib & 0x10) /* if directory */
- return (notAFileErr); /* do nothing and return error */
-
- parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */
-
- /* If creator not 0x00000000, change creator */
- if (creator != (OSType)0x00000000)
- pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
-
- /* If fileType not 0x00000000, change fileType */
- if (fileType != (OSType)0x00000000)
- pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
-
- pb.hFileInfo.ioDirID = dirID;
- error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */
-
- if ((error == noErr) && (parID != fsRtParID)) /* can't bump fsRtParID */
- error = BumpDate(vRefNum, parID, nil);
- /* and bump the parent directory's mod date to wake up the Finder */
- /* to the change we just made */
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpChangeCreatorType(const FSSpec *spec,
- OSType creator,
- OSType fileType)
- {
- return (ChangeCreatorType(spec->vRefNum, spec->parID, spec->name, creator, fileType));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ChangeFDFlags(short vRefNum,
- long dirID,
- StringPtr name,
- Boolean setBits,
- unsigned short flagBits)
- {
- CInfoPBRec pb;
- OSErr error;
- long parID;
-
- pb.hFileInfo.ioNamePtr = name;
- pb.hFileInfo.ioVRefNum = vRefNum;
- pb.hFileInfo.ioDirID = dirID;
- pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- error = PBGetCatInfoSync(&pb);
- if (error == noErr)
- {
- parID = pb.hFileInfo.ioFlParID; /* save parent dirID for BumpDate call */
-
- pb.hFileInfo.ioFlFndrInfo.fdFlags = (setBits) ?
- (pb.hFileInfo.ioFlFndrInfo.fdFlags | flagBits) : /* OR in the bits */
- (pb.hFileInfo.ioFlFndrInfo.fdFlags & (0xffff ^ flagBits)); /* AND out the bits */
- /* set or clear the appropriate bits in the Finder flags */
-
- pb.hFileInfo.ioDirID = dirID;
- error = PBSetCatInfoSync(&pb); /* now, save the new information back to disk */
-
- if ((error == noErr) && (parID != fsRtParID)) /* can't bump fsRtParID */
- error = BumpDate(vRefNum, parID, nil);
- /* and bump the parent directory's mod date to wake up the Finder */
- /* to the change we just made */
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpChangeFDFlags(const FSSpec *spec,
- Boolean setBits,
- unsigned short flagBits)
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, setBits, flagBits));
- }
-
- /*****************************************************************************/
-
- pascal OSErr SetIsInvisible(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, make it invisible. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, true, 0x4000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpSetIsInvisible(const FSSpec *spec)
- /* Given a file or directory, make it invisible. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, true, 0x4000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ClearIsInvisible(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, make it visible. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, false, 0x4000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpClearIsInvisible(const FSSpec *spec)
- /* Given a file or directory, make it visible. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, false, 0x4000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr SetNameLocked(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, lock its name. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, true, 0x1000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpSetNameLocked(const FSSpec *spec)
- /* Given a file or directory, lock its name. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, true, 0x1000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ClearNameLocked(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, unlock its name. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, false, 0x1000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpClearNameLocked(const FSSpec *spec)
- /* Given a file or directory, unlock its name. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, false, 0x1000));
- }
-
- /*****************************************************************************/
-
- pascal OSErr SetIsStationery(short vRefNum,
- long dirID,
- const Str255 name)
- /* Given a file, make it a stationery pad. */
- {
- return (ChangeFDFlags(vRefNum, dirID, (StringPtr)name, true, 0x0800));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpSetIsStationery(const FSSpec *spec)
- /* Given a file, make it a stationery pad. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, true, 0x0800));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ClearIsStationery(short vRefNum,
- long dirID,
- const Str255 name)
- /* Given a file, clear the stationery bit. */
- {
- return (ChangeFDFlags(vRefNum, dirID, (StringPtr)name, false, 0x0800));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpClearIsStationery(const FSSpec *spec)
- /* Given a file, clear the stationery bit. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, false, 0x0800));
- }
-
- /*****************************************************************************/
-
- pascal OSErr SetHasCustomIcon(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, indicate that it has a custom icon. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, true, 0x0400));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpSetHasCustomIcon(const FSSpec *spec)
- /* Given a file or directory, indicate that it has a custom icon. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, true, 0x0400));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ClearHasCustomIcon(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file or directory, indicate that it does not have a custom icon. */
- {
- return (ChangeFDFlags(vRefNum, dirID, name, false, 0x0400));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpClearHasCustomIcon(const FSSpec *spec)
- /* Given a file or directory, indicate that it does not have a custom icon. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, false, 0x0400));
- }
-
- /*****************************************************************************/
-
- pascal OSErr ClearHasBeenInited(short vRefNum,
- long dirID,
- StringPtr name)
- /* Given a file, clear its "has been inited" bit. */
- {
- return (ChangeFDFlags(vRefNum, dirID, (StringPtr)name, false, 0x0100));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpClearHasBeenInited(const FSSpec *spec)
- /* Given a file, clear its "has been inited" bit. */
- {
- return (ChangeFDFlags(spec->vRefNum, spec->parID, (StringPtr)spec->name, false, 0x0100));
- }
-
- /*****************************************************************************/
-
- pascal OSErr CopyFileMgrAttributes(short srcVRefNum,
- long srcDirID,
- StringPtr srcName,
- short dstVRefNum,
- long dstDirID,
- StringPtr dstName,
- Boolean copyLockBit)
- {
- UniversalFMPB pb;
- OSErr error;
- Boolean objectIsDirectory;
-
- pb.ciPB.hFileInfo.ioVRefNum = srcVRefNum;
- pb.ciPB.hFileInfo.ioDirID = srcDirID;
- pb.ciPB.hFileInfo.ioNamePtr = srcName;
- pb.ciPB.hFileInfo.ioFDirIndex = 0;
- error = PBGetCatInfoSync(&pb.ciPB);
- if (error == noErr)
- {
- objectIsDirectory = (pb.ciPB.hFileInfo.ioFlAttrib & 0x10);
- pb.ciPB.hFileInfo.ioVRefNum = dstVRefNum;
- pb.ciPB.hFileInfo.ioDirID = dstDirID;
- pb.ciPB.hFileInfo.ioNamePtr = dstName;
- /* don't copy the hasBeenInited bit */
- pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags = (pb.ciPB.hFileInfo.ioFlFndrInfo.fdFlags & 0xfeff);
- error = PBSetCatInfoSync(&pb.ciPB);
- if ((error == noErr) && (copyLockBit) && (pb.ciPB.hFileInfo.ioFlAttrib & 0x01))
- {
- error = PBHSetFLockSync(&pb.hPB);
- if ((error != noErr) && (objectIsDirectory))
- error = noErr; /* ignore lock errors if destination is directory */
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpCopyFileMgrAttributes(const FSSpec *srcSpec,
- const FSSpec *dstSpec,
- Boolean copyLockBit)
- {
- return (CopyFileMgrAttributes(srcSpec->vRefNum, srcSpec->parID, (StringPtr)srcSpec->name,
- dstSpec->vRefNum, dstSpec->parID, (StringPtr)dstSpec->name,
- copyLockBit));
- }
-
- /*****************************************************************************/
-
- pascal OSErr HOpenAware(short vRefNum,
- long dirID,
- const Str255 fileName,
- short denyModes,
- short *refNum)
- {
- HParamBlockRec pb;
- OSErr error;
- GetVolParmsInfoBuffer volParmsInfo;
- long infoSize = sizeof(GetVolParmsInfoBuffer);
-
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioMisc = nil;
- pb.fileParam.ioNamePtr = (StringPtr)fileName;
- pb.fileParam.ioVRefNum = vRefNum;
- pb.fileParam.ioDirID = dirID;
-
- /* get volume attributes */
- /* this preflighting is needed because Foreign File Access based file systems don't */
- /* return the correct error result to the OpenDeny call */
- error = HGetVolParms((StringPtr)fileName, vRefNum, &volParmsInfo, &infoSize);
- if (error == noErr)
- {
- /* if volume supports OpenDeny, use it and return */
- if (hasOpenDeny(volParmsInfo))
- {
- pb.accessParam.ioDenyModes = denyModes;
- error = PBHOpenDenySync(&pb);
- *refNum = pb.ioParam.ioRefNum;
- return (error);
- }
- }
- else if (error != paramErr) /* paramErr is OK, it just means this volume doesn't support GetVolParms */
- return (error);
-
- /* OpenDeny isn't supported, so try File Manager Open functions */
- /* Set File Manager permissions to closest thing possible */
- pb.ioParam.ioPermssn = ((denyModes == dmWr) || (denyModes == dmRdWr)) ? (fsRdWrShPerm) : (denyModes % 4);
-
- error = PBHOpenDFSync(&pb); /* Try OpenDF */
- if (error == paramErr)
- error = PBHOpenSync(&pb); /* OpenDF not supported, so try Open */
- *refNum = pb.ioParam.ioRefNum;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpOpenAware(const FSSpec *spec,
- short denyModes,
- short *refNum)
- {
- return (HOpenAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum));
- }
-
- /*****************************************************************************/
-
- pascal OSErr HOpenRFAware(short vRefNum,
- long dirID,
- const Str255 fileName,
- short denyModes,
- short *refNum)
- {
- HParamBlockRec pb;
- OSErr error;
- GetVolParmsInfoBuffer volParmsInfo;
- long infoSize = sizeof(GetVolParmsInfoBuffer);
-
- pb.ioParam.ioVersNum = 0;
- pb.ioParam.ioMisc = nil;
- pb.fileParam.ioNamePtr = (StringPtr)fileName;
- pb.fileParam.ioVRefNum = vRefNum;
- pb.fileParam.ioDirID = dirID;
-
- /* get volume attributes */
- /* this preflighting is needed because Foreign File Access based file systems don't */
- /* return the correct error result to the OpenRFDeny call */
- error = HGetVolParms((StringPtr)fileName, vRefNum, &volParmsInfo, &infoSize);
- if (error == noErr)
- {
- /* if volume supports OpenRFDeny, use it and return */
- if (hasOpenDeny(volParmsInfo))
- {
- pb.accessParam.ioDenyModes = denyModes;
- error = PBHOpenRFDenySync(&pb);
- *refNum = pb.ioParam.ioRefNum;
- return (error);
- }
- }
- else if (error != paramErr) /* paramErr is OK, it just means this volume doesn't support GetVolParms */
- return (error);
-
- /* OpenRFDeny isn't supported, so try File Manager OpenRF function */
- /* Set File Manager permissions to closest thing possible */
- pb.ioParam.ioPermssn = ((denyModes == dmWr) || (denyModes == dmRdWr)) ? (fsRdWrShPerm) : (denyModes % 4);
-
- error = PBHOpenRFSync(&pb);
- *refNum = pb.ioParam.ioRefNum;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpOpenRFAware(const FSSpec *spec,
- short denyModes,
- short *refNum)
- {
- return (HOpenRFAware(spec->vRefNum, spec->parID, spec->name, denyModes, refNum));
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSReadNoCache(short refNum,
- long *count,
- void *buffPtr)
- {
- ParamBlockRec pb;
- OSErr error;
-
- pb.ioParam.ioRefNum = refNum;
- pb.ioParam.ioBuffer = (Ptr)buffPtr;
- pb.ioParam.ioReqCount = *count;
- pb.ioParam.ioPosMode = fsAtMark + 0x0020; /* fsAtMark + noCacheBit */
- pb.ioParam.ioPosOffset = 0;
- error = PBReadSync(&pb);
- *count = pb.ioParam.ioActCount;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSWriteNoCache(short refNum,
- long *count,
- const void *buffPtr)
- {
- ParamBlockRec pb;
- OSErr error;
-
- pb.ioParam.ioRefNum = refNum;
- pb.ioParam.ioBuffer = (Ptr)buffPtr;
- pb.ioParam.ioReqCount = *count;
- pb.ioParam.ioPosMode = fsAtMark + 0x0020; /* fsAtMark + noCacheBit */
- pb.ioParam.ioPosOffset = 0;
- error = PBWriteSync(&pb);
- *count = pb.ioParam.ioActCount;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr CopyFork(short srcRefNum,
- short dstRefNum,
- void *copyBufferPtr,
- long copyBufferSize)
- {
- ParamBlockRec srcPB;
- ParamBlockRec dstPB;
- OSErr srcError;
- OSErr dstError;
-
- if ((copyBufferPtr == nil) || (copyBufferSize == 0))
- return (paramErr);
-
- srcPB.ioParam.ioRefNum = srcRefNum;
- dstPB.ioParam.ioRefNum = dstRefNum;
-
- /* preallocate the destination fork and */
- /* ensure the destination fork's EOF is correct after the copy */
- srcError = PBGetEOFSync(&srcPB);
- if (srcError != noErr)
- return (srcError);
- dstPB.ioParam.ioMisc = srcPB.ioParam.ioMisc;
- dstError = PBSetEOFSync(&dstPB);
- if (dstError != noErr)
- return (dstError);
-
- /* reset source fork's mark */
- srcPB.ioParam.ioPosMode = fsFromStart;
- srcPB.ioParam.ioPosOffset = 0;
- srcError = PBSetFPosSync(&srcPB);
- if (srcError != noErr)
- return (srcError);
-
- /* reset destination fork's mark */
- dstPB.ioParam.ioPosMode = fsFromStart;
- dstPB.ioParam.ioPosOffset = 0;
- dstError = PBSetFPosSync(&srcPB);
- if (dstError != noErr)
- return (dstError);
-
- /* set up fields that won't change in the loop */
- srcPB.ioParam.ioBuffer = (Ptr)copyBufferPtr;
- srcPB.ioParam.ioPosMode = fsAtMark + 0x0020;/* fsAtMark + noCacheBit */
- srcPB.ioParam.ioReqCount = ((copyBufferSize >= 512) && (copyBufferSize % 512)) ? (copyBufferSize / 512) * 512 : (copyBufferSize);
- /* If copyBufferSize is greater than 512 bytes, make it a multiple of 512 bytes */
- /* This will make writes on local volumes faster */
-
- dstPB.ioParam.ioBuffer = (Ptr)copyBufferPtr;
- dstPB.ioParam.ioPosMode = fsAtMark + 0x0020;/* fsAtMark + noCacheBit */
-
- while ((srcError == noErr) && (dstError == noErr))
- {
- srcError = PBReadSync(&srcPB);
- dstPB.ioParam.ioReqCount = srcPB.ioParam.ioActCount;
- dstError = PBWriteSync(&dstPB);
- }
-
- /* make sure there were no errors at the destination */
- if (dstError != noErr)
- return (dstError);
-
- /* make sure the only error at the source was eofErr */
- if (srcError != eofErr)
- return (srcError);
-
- return (noErr);
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetFileLocation(short refNum,
- short *vRefNum,
- long *dirID,
- StringPtr fileName)
- {
- FCBPBRec pb;
- OSErr error;
-
- pb.ioNamePtr = fileName;
- pb.ioVRefNum = 0;
- pb.ioRefNum = refNum;
- pb.ioFCBIndx = 0;
- error = PBGetFCBInfoSync(&pb);
- *vRefNum = pb.ioFCBVRefNum;
- *dirID = pb.ioFCBParID;
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpGetFileLocation(short refNum,
- FSSpec *spec)
- {
- return (GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name));
- }
-
- /*****************************************************************************/
-
- pascal OSErr CopyDirectoryAccess(short srcVRefNum,
- long srcDirID,
- StringPtr srcName,
- short dstVRefNum,
- long dstDirID,
- StringPtr dstName)
- {
- OSErr err;
- GetVolParmsInfoBuffer infoBuffer; /* Where PBGetVolParms dumps its info */
- long dstServerAdr; /* AppleTalk server address of destination (if any) */
- Boolean dstHasBlankAccessPrivileges;
- long ownerID, groupID, accessRights;
- long tempLong;
-
- /* See if destination supports directory access control */
- tempLong = sizeof(infoBuffer);
- err = HGetVolParms(dstName, dstVRefNum, &infoBuffer, &tempLong);
- if ((err != noErr) && (err != paramErr))
- return (err);
- if ((err != paramErr) && hasAccessCntl(infoBuffer)) {
- dstServerAdr = infoBuffer.vMServerAdr;
- dstHasBlankAccessPrivileges = hasBlankAccessPrivileges(infoBuffer);
- }
- else
- /* If destination doesn't support access privileges, */
- /* then there's nothing left to do here */
- return (noErr);
-
- /* We may have to do something with access privileges at the destination. */
-
- accessRights = 0; /* clear so we can tell if anything was done with this */
-
- /* See if source supports directory access control and is on same server */
- tempLong = sizeof(infoBuffer);
- err = HGetVolParms(srcName, srcVRefNum, &infoBuffer, &tempLong);
- if ((err != noErr) && (err != paramErr))
- return (err);
- if ((err != paramErr) && hasAccessCntl(infoBuffer)) {
- /* Make sure both locations are on the same file server */
- if (dstServerAdr == infoBuffer.vMServerAdr) {
- /* copy'm */
- err = HGetDirAccess(srcVRefNum, srcDirID, srcName, &ownerID, &groupID, &accessRights);
- if (err == noErr)
- err = HSetDirAccess(dstVRefNum, dstDirID, dstName, ownerID, groupID, accessRights);
- }
- }
- return (err);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpCopyDirectoryAccess(const FSSpec *srcSpec,
- const FSSpec *dstSpec)
- {
- return (CopyDirectoryAccess(srcSpec->vRefNum, srcSpec->parID, (StringPtr)srcSpec->name,
- dstSpec->vRefNum, dstSpec->parID, (StringPtr)dstSpec->name));
- }
-
- /*****************************************************************************/
-
- pascal OSErr HMoveRenameCompat(short vRefNum,
- long srcDirID,
- const Str255 srcName,
- long dstDirID,
- StringPtr dstpathName,
- StringPtr copyName)
- {
- OSErr error;
- GetVolParmsInfoBuffer volParmsInfo;
- long infoSize = sizeof(GetVolParmsInfoBuffer);
- short realVRefNum;
- long realParID;
- Str255 realName;
- short tempItemsVRefNum;
- long tempItemsDirID;
- Boolean isDirectory;
-
- /* get volume attributes */
- error = HGetVolParms((StringPtr)srcName, vRefNum, &volParmsInfo, &infoSize);
- if (error == noErr)
- {
- /* if volume supports move and rename, use it and return */
- if (hasMoveRename(volParmsInfo))
- return (HMoveRename(vRefNum, srcDirID, srcName, dstDirID, dstpathName, copyName));
- }
- else if (error != paramErr) /* paramErr is OK, it just means this volume doesn't support GetVolParms */
- return (error);
-
- /* MoveRename isn't supported by this volume, so do it by hand */
-
- /* if copyName isn't supplied, we can simply CatMove and return */
- if (copyName == nil)
- return (CatMove(vRefNum, srcDirID, srcName, dstDirID, dstpathName));
-
- /* renaming is required, so we have some work to do... */
-
- /* get the object's real name */
- error = GetObjectLocation(vRefNum, srcDirID, (StringPtr)srcName,
- &realVRefNum, &realParID, realName, &isDirectory);
- if (error != noErr)
- return (error);
-
- /* find temporary items folder */
- error = FindFolder(realVRefNum, kTemporaryFolderType, kCreateFolder,
- &tempItemsVRefNum, &tempItemsDirID);
- if (error != noErr)
- return (error);
-
- /* move the object to a temporary items folder for renaming */
- error = CatMove(realVRefNum, realParID, realName, tempItemsDirID, nil);
- if (error != noErr)
- return (error);
-
- /* rename the object */
- error = HRename(tempItemsVRefNum, tempItemsDirID, realName, copyName);
- if (error == noErr)
- {
- /* move object to its new home */
- error = CatMove(tempItemsVRefNum, tempItemsDirID, copyName, dstDirID, dstpathName);
- if (error == noErr)
- return (error); /* IF NO ERRORS EXIT HERE! */
-
- /* Error handling: rename object back to original name - keep real error */
- (void) HRename(tempItemsVRefNum, tempItemsDirID, copyName, realName);
- }
-
- /* Error handling: move object back to original location - keep real error */
- (void) CatMove(tempItemsVRefNum, tempItemsDirID, realName, realParID, nil);
-
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpMoveRenameCompat(const FSSpec *srcSpec,
- const FSSpec *dstSpec,
- StringPtr copyName)
- {
- /* make sure the FSSpecs refer to the same volume */
- if (srcSpec->vRefNum != dstSpec->vRefNum)
- return (diffVolErr);
- return (HMoveRenameCompat(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
- dstSpec->parID, (StringPtr)dstSpec->name, copyName));
- }
-
- /*****************************************************************************/
-
- pascal void BuildAFPVolMountInfo(short theFlags,
- char theNBPInterval,
- char theNBPCount,
- short theUAMType,
- Str31 theZoneName,
- Str31 theServerName,
- Str27 theVolName,
- Str31 theUserName,
- Str8 theUserPassWord,
- Str8 theVolPassWord,
- MyAFPVolMountInfoPtr theAFPInfo)
- {
- /* Fill in an AFPVolMountInfo record that can be passed to VolumeMount */
- theAFPInfo->length = sizeof(MyAFPVolMountInfo);
- theAFPInfo->media = AppleShareMediaType;
- theAFPInfo->flags = theFlags;
- theAFPInfo->nbpInterval = theNBPInterval;
- theAFPInfo->nbpCount = theNBPCount;
- theAFPInfo->uamType = theUAMType;
- theAFPInfo->zoneNameOffset = (short)((long)theAFPInfo->zoneName - (long)theAFPInfo);
- theAFPInfo->serverNameOffset = (short)((long)theAFPInfo->serverName - (long)theAFPInfo);
- theAFPInfo->volNameOffset = (short)((long)theAFPInfo->volName - (long)theAFPInfo);
- theAFPInfo->userNameOffset = (short)((long)theAFPInfo->userName - (long)theAFPInfo);
- theAFPInfo->userPasswordOffset = (short)((long)theAFPInfo->userPassword - (long)theAFPInfo);
- theAFPInfo->volPasswordOffset = (short)((long)theAFPInfo->volPassword - (long)theAFPInfo);
- pcpy(theAFPInfo->zoneName, theZoneName);
- pcpy(theAFPInfo->serverName, theServerName);
- pcpy(theAFPInfo->volName, theVolName);
- pcpy(theAFPInfo->userName, theUserName);
- pcpy(theAFPInfo->userPassword, theUserPassWord);
- pcpy(theAFPInfo->volPassword, theVolPassWord);
- }
-
- /*****************************************************************************/
-
- pascal OSErr RetrieveAFPVolMountInfo(AFPVolMountInfoPtr theAFPInfo,
- short *theFlags,
- short *theUAMType,
- StringPtr theZoneName,
- StringPtr theServerName,
- StringPtr theVolName,
- StringPtr theUserName)
- {
- /* Retrieve the AFP mounting information from an AFPVolMountInfo record. */
- if (theAFPInfo->media != AppleShareMediaType)
- return (paramErr);
-
- *theFlags = theAFPInfo->flags;
- *theUAMType = theAFPInfo->uamType;
- pcpy(theZoneName, (StringPtr)((long)theAFPInfo + theAFPInfo->zoneNameOffset));
- pcpy(theServerName, (StringPtr)((long)theAFPInfo + theAFPInfo->serverNameOffset));
- pcpy(theVolName, (StringPtr)((long)theAFPInfo + theAFPInfo->volNameOffset));
- pcpy(theUserName, (StringPtr)((long)theAFPInfo + theAFPInfo->userNameOffset));
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetUGEntries(short objType,
- UGEntryPtr entries,
- long reqEntryCount,
- long *actEntryCount,
- long *objID)
- {
- HParamBlockRec pb;
- OSErr error = noErr;
- UGEntry *endEntryArray = entries + reqEntryCount;
-
- pb.objParam.ioObjType = objType;
- *actEntryCount = 0;
- for (; (entries < endEntryArray) && (error == noErr); ++entries)
- {
- pb.objParam.ioObjNamePtr = (StringPtr)entries->name;
- pb.objParam.ioObjID = *objID;
- /* Files.h in the universal interfaces, PBGetUGEntrySync takes a CMovePBPtr */
- /* as the parameter. Inside Macintosh and the original glue used HParmBlkPtr. */
- /* A CMovePBPtr works OK, but this will be changed in the future back to */
- /* HParmBlkPtr, so I'm just casting it here. */
- error = PBGetUGEntrySync((CMovePBPtr)&pb);
- if (error == noErr)
- {
- entries->objID = *objID = pb.objParam.ioObjID;
- entries->objType = objType;
- ++*actEntryCount;
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- /* Desktop Manager calls */
-
- /*****************************************************************************/
-
- pascal OSErr CopyComment(short srcVRefNum,
- long srcDirID,
- StringPtr srcName,
- short dstVRefNum,
- long dstDirID,
- StringPtr dstName)
- /* Both volumes must support the Desktop Manager for this to work */
- {
- DTPBRec pb;
- OSErr error;
- unsigned char commentBuffer[199];
- long commentLength;
-
- pb.ioNamePtr = srcName;
- pb.ioVRefNum = srcVRefNum;
- error = PBDTOpenInform(&pb);
- if (error == paramErr)
- error = PBDTGetPath(&pb);
- if (error == noErr)
- {
- pb.ioNamePtr = srcName;
- pb.ioDirID = srcDirID;
- pb.ioDTBuffer = (Ptr) & commentBuffer;
- error = PBDTGetCommentSync(&pb);
- if (error == noErr)
- {
- commentLength = pb.ioDTActCount;
- pb.ioNamePtr = dstName;
- pb.ioVRefNum = dstVRefNum;
- error = PBDTOpenInform(&pb);
- if (error == paramErr)
- error = PBDTGetPath(&pb);
- if (error == noErr)
- {
- pb.ioNamePtr = dstName;
- pb.ioDirID = dstDirID;
- pb.ioDTBuffer = (Ptr) & commentBuffer;
- pb.ioDTReqCount = commentLength;
- error = PBDTSetCommentSync(&pb);
- }
- }
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpCopyComment(const FSSpec *srcSpec,
- const FSSpec *dstSpec)
- /* Both volumes must support the Desktop Manager for this to work */
- {
- return (CopyComment(srcSpec->vRefNum, srcSpec->parID, (StringPtr)srcSpec->name,
- dstSpec->vRefNum, dstSpec->parID, (StringPtr)dstSpec->name));
- }
-
- /*****************************************************************************/
-
- pascal OSErr SetComment(short vRefNum,
- long dirID,
- StringPtr name,
- const Str255 comment)
- {
- DTPBRec pb;
- OSErr error;
-
- pb.ioNamePtr = name;
- pb.ioVRefNum = vRefNum;
- error = PBDTOpenInform(&pb);
- if (error == paramErr)
- error = PBDTGetPath(&pb);
- if (error == noErr)
- {
- pb.ioNamePtr = name;
- pb.ioDirID = dirID;
- pb.ioDTBuffer = (Ptr)&comment[1];
- pb.ioDTReqCount = comment[0];
- error = PBDTSetCommentSync(&pb);
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpSetComment(const FSSpec *spec,
- const Str255 comment)
- {
- return (SetComment(spec->vRefNum, spec->parID, (StringPtr)spec->name, comment));
- }
-
- /*****************************************************************************/
-
- pascal OSErr GetComment(short vRefNum,
- long dirID,
- StringPtr name,
- StringPtr comment)
- {
- DTPBRec pb;
- OSErr error;
-
- if (comment == nil)
- return (paramErr);
-
- pb.ioNamePtr = name;
- pb.ioVRefNum = vRefNum;
- error = PBDTOpenInform(&pb);
- if (error == paramErr)
- error = PBDTGetPath(&pb);
- if (error == noErr)
- {
- pb.ioNamePtr = name;
- pb.ioDirID = dirID;
- pb.ioDTBuffer = (Ptr)&comment[1];
- error = PBDTGetCommentSync(&pb);
- if (error == noErr)
- comment[0] = (unsigned char)pb.ioDTActCount;
- else
- comment[0] = 0;
- }
- return (error);
- }
-
- /*****************************************************************************/
-
- pascal OSErr FSpGetComment(const FSSpec *spec,
- StringPtr comment)
- {
- return (GetComment(spec->vRefNum, spec->parID, (StringPtr)spec->name, comment));
- }
-
- /*****************************************************************************/
-
-